package br.com.light.adapter.envio.lote;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.TransformService;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.jcp.xml.dsig.internal.dom.DOMTransform;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.DOMOutputter;
import org.jdom.output.XMLOutputter;

import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.StreamTransformation;
import com.sap.aii.mapping.api.StreamTransformationConstants;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.utilxi.base64.api.Base64;
import com.sap.security.core.server.ssf.SsfProfileKeyStore;

public class MappingEnvioLoteRFCSP implements StreamTransformation {

	
	private AbstractTrace trace = null;
	private Map mapTrace = null;
	public final static int INSC_PREST = 8;
	public final static int SERIE_RPS = 5;
	public final static int NUM_RPS = 12;
	public final static int EMISSAO_RPS = 8;
	public final static int ISS_RETIDO = 1;
	public final static int MOEDA = 15;
	public final static int COD_SERVICO = 5;
	public final static int CPFCNPJ = 14;

	
	/**
	 * @param args
	 * @throws FileNotFoundException 
	 * @throws StreamTransformationException 
	 */
	public static void main(String[] args) throws FileNotFoundException, StreamTransformationException {
		File file = new File("D:/documentos/Complex/Light/schema/LoteRPS/Envio/ZNFSEF_SHIP_SENDING_OUT_TESTSP_4.xml");
		InputStream in = new FileInputStream(file);
			
		File fileOut = new File("D:/documentos/Complex/Light/schema/LoteRPS/envio/EnvioLoteRFCSPOut_1.xml");
		OutputStream out = new FileOutputStream(fileOut);
		
		new MappingEnvioLoteRFCSP().execute(in, out);
	}
	
	public void execute(InputStream in, OutputStream out)
			throws StreamTransformationException {
		
		trace = (AbstractTrace) mapTrace.get(StreamTransformationConstants.MAPPING_TRACE);

		String zinscprest = "";
		String zserierps = "";
		String znumerorps = "";
		String zdataemissao = "";
		String ztributacaorps = "";
		String zstatusrps = "";
		String zissretido = "";
		String zvlinss = "";
		String zvlservico = "";
		String zvldeducoes = "";
		String zcodserv = "";
		String zindCNPJTomador = "2";
		String zcnpjtomador = "";				
		
		try {
			
			trace.addInfo("1 - Metodo execute - Inicio");

			
			Element header = new Element("PedidoEnvioLoteRPS", "ns0", "http://www.prefeitura.sp.gov.br/nfe");
			//mensagemXML.addContent(header);
	
			Element cabecalho = new Element("Cabecalho");
			cabecalho.setAttribute("Versao", "1");
			header.addContent(cabecalho);
			
			Element cpfcnpjrementente = new Element("CPFCNPJRemetente");
			cabecalho.addContent(cpfcnpjrementente);
			Element cnpj = new Element("CNPJ");
			cpfcnpjrementente.addContent(cnpj);
			Element transacao = new Element("transacao");
			cabecalho.addContent(transacao);
			Element dtInicio = new Element("dtInicio");
			cabecalho.addContent(dtInicio);
			Element dtFim = new Element("dtFim");
			cabecalho.addContent(dtFim);
			Element qtdRPS = new Element("QtdRPS");
			cabecalho.addContent(qtdRPS);
			Element vlTotalSrv = new Element("ValorTotalServicos");
			cabecalho.addContent(vlTotalSrv);
			Element vlTotalDedu = new Element("ValorTotalDeducoes");
			cabecalho.addContent(vlTotalDedu);
			
			Element assinatura = new Element("Assinatura");
			
			
			Element rps = new Element("RPS");
			header.addContent(rps);
			rps.addContent(assinatura);
					//assinatura.setText(elem.getChildText("Assinatura"));
			Element chaveRpsStructure = new Element("ChaveRPS");
			rps.addContent(chaveRpsStructure);
			Element inscricaoPrestador = new Element("InscricaoPrestador");
			chaveRpsStructure.addContent(inscricaoPrestador);
			//inscprest = elemRPS.getChildText("InscricaoPrestador");
			//inscricaoPrestador.setText(inscprest);
			
			Element serieRPS = new Element("SerieRPS");
			chaveRpsStructure.addContent(serieRPS);
	//		serierps =  elemRPS.getChildText("SerieRPS");
	//		serieRPS.setText(serierps);
			
			Element numeroRPS = new Element("NumeroRPS");
			chaveRpsStructure.addContent(numeroRPS);
	//		numerorps = elemRPS.getChildText("NumeroRPS");
	//		numeroRPS.setText(numerorps);
			
			Element tipoRPS = new Element("TipoRPS");
			rps.addContent(tipoRPS);
	//		tipoRPS.setText(elem.getChildText("TipoRPS"));
			
			
			Element dataEmissao =  new Element("DataEmissao");
			rps.addContent(dataEmissao);
	//		dataemissao = elem.getChildText("DataEmissao");	
	//		dataEmissao.setText(dataemissao);
			
			Element statusRPS = new Element("StatusRPS");
			rps.addContent(statusRPS);
	//		statusrps = elem.getChildText("StatusRPS");
	//		statusRPS.setText(statusrps);
			
			Element tributacaoRPS = new Element("TributacaoRPS");
			rps.addContent(tributacaoRPS);
	//		tributacaorps = elem.getChildText("TributacaoRPS");
	//		tributacaoRPS.setText(tributacaorps);
			
			Element valorServicos = new Element("ValorServicos");
			rps.addContent(valorServicos);
	//		vlservico = elem.getChildText("ValorServicos");
	//		valorServicos.setText(vlservico);
			
			Element valorDeducoes = new Element("ValorDeducoes");
			rps.addContent(valorDeducoes);
	//		vldeducoes = elem.getChildText("ValorDeducoes");
	//		valorDeducoes.setText(vldeducoes);
			
			Element valorPIS = new Element("ValorPIS");
			rps.addContent(valorPIS);
	//		valorPIS.setText(elem.getChildText("ValorPIS"));
			
			Element valorCOFINS = new Element("ValorCOFINS");
			rps.addContent(valorCOFINS);
	//		valorCOFINS.setText(elem.getChildText("ValorCOFINS"));
			
			Element valorINSS = new Element("ValorINSS");
			rps.addContent(valorINSS);
	//		vlinss = elem.getChildText("ValorINSS");
	//		valorINSS.setText(vlinss);
			
			Element valorIR = new Element("ValorIR");
			rps.addContent(valorIR);
	//		valorIR.setText(elem.getChildText("ValorIR"));
			
			Element valorCSLL = new Element("ValorCSLL");
			rps.addContent(valorCSLL);
	//		valorCSLL.setText(elem.getChildText("ValorCSLL"));
			
			Element codigoServico = new Element("CodigoServico");
			rps.addContent(codigoServico);
	//		codserv = elem.getChildText("CodigoServico");
	//		codigoServico.setText(codserv);
			
			Element aliquotaServicos = new Element("AliquotaServicos");
			rps.addContent(aliquotaServicos);
	//		aliquotaServicos.setText(elem.getChildText("AliquotaServicos"));
			
			Element iSSRetido = new Element("ISSRetido");
			rps.addContent(iSSRetido);
	//		iSSRetido.setText(elem.getChildText("ISSRetido"));
	/*		if ("true".equals(elem.getChildText("ISSRetido"))){
				issretido = "S";
			}else {
				issretido = "N";
			}*/
					
			Element cpfcnpjTomadorStructure = new Element("CPFCNPJTomador");
			rps.addContent(cpfcnpjTomadorStructure);
			Element elemCnpjTomador = new Element("CNPJ");
			cpfcnpjTomadorStructure.addContent(elemCnpjTomador);
	//		cnpjtomador = elemCPFCNPJTomador.getChildText("CNPJ");
	//		elemCnpjTomador.setText(cnpjtomador);
			Element inscricaoMunicipalTomador = new Element("InscricaoMunicipalTomador");
			rps.addContent(inscricaoMunicipalTomador);
	//		inscricaoMunicipalTomador.setText(elem.getChildText("InscricaoMunicipalTomador"));
			/*Element inscricaoEstadualTomador = new Element("InscricaoEstadualTomador");
			rpsStructure.addContent(inscricaoEstadualTomador);*/
					
			Element razaoSocialTomador = new Element("RazaoSocialTomador");
	//		rps.addContent(razaoSocialTomador);
	//		razaoSocialTomador.setText(elem.getChildText("RazaoSocialTomador"));
					
			Element enderecoTomadorStructure = new Element("EnderecoTomador");
			rps.addContent(enderecoTomadorStructure);
			Element tipoLogradouroTomador = new Element("TipoLogradouro");
			enderecoTomadorStructure.addContent(tipoLogradouroTomador);
	//		tipoLogradouroTomador.setText(elemEnderecoTomador.getChildText("TipoLogradouro"));
				
			Element logradouroTomador = new Element("Logradouro");
			enderecoTomadorStructure.addContent(logradouroTomador);
	//		logradouroTomador.setText(elemEnderecoTomador.getChildText("Logradouro"));
			
			Element numeroEnderecoTomador = new Element("NumeroEndereco");
			enderecoTomadorStructure.addContent(numeroEnderecoTomador);
	//		numeroEnderecoTomador.setText(elemEnderecoTomador.getChildText("NumeroEndereco"));
			
			Element bairroTomador = new Element("Bairro");
			enderecoTomadorStructure.addContent(bairroTomador);
	//		bairroTomador.setText(elemEnderecoTomador.getChildText("Bairro"));
			
			Element cidadeTomador = new Element("Cidade");
			enderecoTomadorStructure.addContent(cidadeTomador);
	//		cidadeTomador.setText(elemEnderecoTomador.getChildText("Cidade"));
	
			Element ufTomador = new Element("UF");
			enderecoTomadorStructure.addContent(ufTomador);
	//		ufTomador.setText(elemEnderecoTomador.getChildText("UF"));
			
			Element cepTomador = new Element("CEP");
			enderecoTomadorStructure.addContent(cepTomador);
	//		cepTomador.setText(elemEnderecoTomador.getChildText("CEP"));
	
			Element emailTomador = new Element("EmailTomador");
			rps.addContent(emailTomador);
	//		emailTomador.setText(elem.getChildText("EmailTomador"));
			
			Element discriminacaoTomador = new Element("Discriminacao");
			rps.addContent(discriminacaoTomador);	
	//		discriminacaoTomador.setText(elem.getChildText("Discriminacao"));
	
			XMLOutputter xmlOutputter = new XMLOutputter();
			
			SAXBuilder sb = new SAXBuilder();
			Document doc = sb.build(in);
			
			String docString = xmlOutputter.outputString(doc);
			trace.addInfo("2 - Metodo execute - XML de Entrada RFC: "+docString);
			
			Element root = doc.getRootElement();
			List elements = root.getChildren();
			Iterator iter = elements.iterator();
			while(iter.hasNext()){
				Element elem = (Element)iter.next();
					
					System.out.println(elem.getName());
					
					String i_amnt_dedu = root.getChildText("I_AMNT_DEDU");
					
					//zvldeducoes = elem.getChildText("AMNT_DEDU");
					zvldeducoes = i_amnt_dedu;
					vlTotalDedu.setText(zvldeducoes);
					
					String i_amnt_serv = root.getChildText("I_AMNT_SERV");
					zvlservico = i_amnt_serv;
					vlTotalSrv.setText(zvlservico);
					
					String i_cnpj = root.getChildText("I_CNPJ");
					
					String i_dat_fim = root.getChildText("I_DAT_FIM");
					dtFim.setText(i_dat_fim);
					
					String i_dat_inicio = root.getChildText("I_DT_INICIO");
					dtInicio.setText(i_dat_inicio);
					
					String i_qtde_rps = root.getChildText("I_QTE_RPS");
					qtdRPS.setText(i_qtde_rps);
				
				
					if("I_RPS".equals(elem.getName())){	
						znumerorps = elem.getChildText("RPSNUM");
						numeroRPS.setText(znumerorps);
					
						zserierps = elem.getChildText("RPS_SERIES");
						String  serieRPSFiltro = tratarDados(zserierps);
						serieRPS.setText(serieRPSFiltro);
						
						String zrpstype = elem.getChildText("RPS_TYPE");
						String rpsTypeFiltro = tratarDados(zrpstype);
						tipoRPS.setText(rpsTypeFiltro);
						
						zdataemissao = elem.getChildText("ISSUE_DATE");
						dataEmissao.setText(zdataemissao);
						
						zstatusrps = elem.getChildText("RPS_STATUS");
						statusRPS.setText(zstatusrps);
							
						ztributacaorps = elem.getChildText("NAT_OPER");
						//elem.getChildText("RET_CODE");
						tributacaoRPS.setText(ztributacaorps);
						
						String amnt_serv = elem.getChildText("AMNT_SERV");
						valorServicos.setText(amnt_serv);
						/*zvlservico = elem.getChildText("AMNT_SERV");
						valorServicos.setText(zvlservico);
						vlTotalSrv.setText(zvlservico);

						zvldeducoes = elem.getChildText("AMNT_DEDU");
						valorDeducoes.setText(zvldeducoes);
						vlTotalDedu.setText(zvldeducoes);*/
		
						String amnt_dedu = elem.getChildText("AMNT_DEDU");
						valorDeducoes.setText(amnt_dedu);
						
						String zvlpis = elem.getChildText("AMNT_PIS");
						valorPIS.setText(zvlpis);
						
						String zvlcofins = elem.getChildText("AMNT_COF");
						valorCOFINS.setText(zvlcofins);
						
						zvlinss = elem.getChildText("AMNT_INSS");
						valorINSS.setText(zvlinss);
						
						String zvlir = elem.getChildText("AMNT_IR");
						valorIR.setText(zvlir);
						
						String zvlcsll = elem.getChildText("AMNT_CSLL");
						valorCSLL.setText(zvlcsll);
						
						zcodserv = elem.getChildText("SERV_ITEM");
						codigoServico.setText(zcodserv);
						
						String zaliquotserv = elem.getChildText("ALIQUOT");
						aliquotaServicos.setText(zaliquotserv);
						
						String issretido = elem.getChildText("ISS_RET");
						iSSRetido.setText(issretido.toLowerCase());
						if ("true".equals(elem.getChildText("ISSRetido"))){
							zissretido = "S";
						}else {
							zissretido = "N";
						}
						
						String ztransacao = elem.getChildText("TRANS");
						transacao.setText(ztransacao);
						
						zcnpjtomador = elem.getChildText("TAKER_CNPJ");
						elemCnpjTomador.setText(zcnpjtomador);
						
						/*String zcpftomador = elem.getChildText("TAKER_CPF");
						cpfTomador.setText(zcpftomador);*/
						
						String zinscmunctomador = elem.getChildText("TAKER_IM");
						inscricaoMunicipalTomador.setText(zinscmunctomador);
						
						String zrazaosocialtomador = elem.getChildText("TAKER_NAME");
						String razaoSocialTomadorFiltro = tratarDados(zrazaosocialtomador);
						razaoSocialTomador.setText(razaoSocialTomadorFiltro);
						
						String zlogradourotomador = elem.getChildText("TAKER_ADDR_STREET");
						String logradouroTomadorFiltro = tratarDados(zlogradourotomador);
						logradouroTomador.setText(logradouroTomadorFiltro);
						
						String znumeroenderecotomador = elem.getChildText("TAKER_ADDR_NUM");
						numeroEnderecoTomador.setText(znumeroenderecotomador);
						
						String zbairrotomador = elem.getChildText("TAKER_ADDR_DIST");
						String bairroTomadorFiltro = tratarDados(zbairrotomador);
						bairroTomador.setText(bairroTomadorFiltro);
						
						String zcidadetomador = elem.getChildText("TAKER_CITY");
						
						String zcodcidadetomador = elem.getChildText("TAKER_CITY_CODE");
						cidadeTomador.setText(zcodcidadetomador);
						
						String zuftomador = elem.getChildText("TAKER_UF");
						ufTomador.setText(zuftomador);
						
						String zceptomador = elem.getChildText("TAKER_ADDR_POST_CODE");
						cepTomador.setText(zceptomador);
						
						String zdiscriminacao = elem.getChildText("TEXT");
						String discriminacaoFiltro = tratarDados(zdiscriminacao);
						discriminacaoTomador.setText(discriminacaoFiltro);
						
						String zemail = elem.getChildText("TAKER_EMAIL");
						if (zemail != null  && !("".equals(zemail))){
							String emailFiltro = tratarDados(zemail);
							emailTomador.setText(emailFiltro);
						}
						
						
						
					}
					if("I_RPS_SHIPMENT".equals(elem.getName())){
						zinscprest = elem.getChildText("IM");
						inscricaoPrestador.setText(zinscprest);

						String zcnpjrementente = elem.getChildText("CNPJ");
						cnpj.setText(zcnpjrementente);
						
						//String counter = elem.getChildText("COUNTER");
						//qtdRPS.setText(counter);
						
					}
			}			
			
			//Realizando a Assinatura Eletronica
			StringBuffer assinaturaSB = new StringBuffer();
			
			String signinscprest = completarZerosEsquerda(zinscprest, INSC_PREST);
			assinaturaSB.append(signinscprest);
			
			String signserierps = completarEspacoBrancoDireita(zserierps, 5);
			assinaturaSB.append(signserierps);
			
			String signnumerorps = removeZeros(znumerorps);
			signnumerorps = completarZerosEsquerda(signnumerorps, NUM_RPS);
			assinaturaSB.append(signnumerorps);
				
			String signdataemissao = tratarDate(zdataemissao);  
			assinaturaSB.append(signdataemissao);
			
			String signtributacaorps = ztributacaorps;
			assinaturaSB.append(signtributacaorps);
			
			String signstatusrps = zstatusrps;
			assinaturaSB.append(signstatusrps);
			
			String signissretido = zissretido;
			assinaturaSB.append(signissretido);
			
			/*String signvlinss = tratarMoeda(vlinss, MOEDA);
			assinaturaSB.append(signvlinss);*/
			
			String signvlservico = tratarMoeda(zvlservico, MOEDA);
			assinaturaSB.append(signvlservico);
			
			String signvldeducoes = tratarMoeda(zvldeducoes, MOEDA);
			assinaturaSB.append(signvldeducoes); 
			
			String signcodserv = completarZerosEsquerda(zcodserv, COD_SERVICO);
			assinaturaSB.append(signcodserv);
			
			String signindCNPJTomador = zindCNPJTomador;
			assinaturaSB.append(signindCNPJTomador);
					
			String signcnpjtomador = completarZerosEsquerda(zcnpjtomador, CPFCNPJ);
			assinaturaSB.append(signcnpjtomador);
			
			assinaturaSB.toString();			
			System.out.println(assinaturaSB.toString());
			
			trace.addInfo("3 - Metodo execute - Assinatura: "+assinaturaSB.toString());
	
			File file = new File(getInfoCertificate("file_certificate"));
			String alias = getInfoCertificate("alias_certificate");
			String password = getInfoCertificate("pass_certificate");
			
			InputStream is = new FileInputStream(file);
			KeyStore ks = KeyStore.getInstance("pkcs12");
			ks.load(is, password.toCharArray());
			is.close();			
			
			PrivateKey key = getPrivateKeyFromFile(ks, alias, password);	
			
			byte [] sign = createSignature(key, assinaturaSB.toString().getBytes());	
			
			String signatureValue = convertSignatureToString(sign);
			
			assinatura.setText(signatureValue);
			
			Document jdoc = new Document(header);
			
			DOMOutputter outputter = new DOMOutputter();
			org.w3c.dom.Document docNative = outputter.output(jdoc);
			org.w3c.dom.Document docSign = assinarDocumento(docNative, ks, alias, key, password);
			
			TransformerFactory tf=TransformerFactory.newInstance();
			Transformer transform=tf.newTransformer();
			
			transform.transform(new DOMSource(docSign), new StreamResult(out));
			
		}catch (JDOMException e) {
			e.printStackTrace();
			
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CertificateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	private String tratarDados(String texto){
		//removendo acentuacao		
/*		String str = Normalizer.normalize(texto, Normalizer.Form.NFD);
		str = str.replaceAll("[^\\p{ASCII}]", "");*/
		
		//Removendo caracteres especiais
		String nfeProcStr = texto.replaceAll("&", "&am	p;").
				  replaceAll( ">", "&gt;").
				  replaceAll("<", "&lt;" ).
				  replaceAll("'", "&apos;").
				  replaceAll( "\"", "&quot;");
		
		return nfeProcStr.toUpperCase();
	}
	
	private String removeZeros(String linha) {  
	    return linha.replaceFirst("0*", "");  
	}  
	
	private String completarZerosEsquerda(String texto, int tamanho){
		while(texto.length() < tamanho){
			texto = "0"+texto;
		}	
		return texto;
	}

	private String tratarDate(String date){
		String data ="";
		if (date.length() > 8){
			System.out.println(date.length());
			 data = date.substring(0, 10);
			data = data.replaceAll("-", "");
			data.trim();
		}else {
			data = date;
		}
		return data;
	}	
	
	private String completarEspacoBrancoDireita(String texto, int tamanho){
		texto = texto.trim();
		while(texto.length() < tamanho){
			texto = texto+" ";
		}
		return texto;
	}
	
	private String tratarMoeda(String texto, int tamanho){
		if(texto.indexOf(".") != -1){
			texto = texto.replaceAll("\\.", "");
		}
		
		texto = completarZerosEsquerda(texto, tamanho);
		
		return texto;
	}
	
	public static PrivateKey getPrivateKeyFromFile( KeyStore ks, String alias, String password ) throws Exception {  
	    Key key = ks.getKey( alias, password.toCharArray() );  
	    if( key instanceof PrivateKey ) {  
	        return (PrivateKey) key;  
	    }  
	    return null;  
	}  
	
	private String getInfoCertificate(String key){
		Locale locale = new Locale("en", "US");
		ResourceBundle rb = ResourceBundle.getBundle("resource", locale);
		String value =rb.getString(key);
		
		return value;
	}
	
	private byte[] createSignature( PrivateKey key, byte[] buffer ) throws Exception {  
	    Signature sig = Signature.getInstance( "SHA1withRSA" );  
	    sig.initSign(key);  
	    sig.update(buffer, 0, buffer.length);  
	    return sig.sign();  
	}  	
	
	private String convertSignatureToString(byte [] signature) throws UnsupportedEncodingException{
		
		Base64 encode = new Base64();
		String assinatura = encode.encode(signature);
		System.out.println("Assinatura: "+assinatura);
		System.out.println();
		String assinaturaUtF8 = new String(assinatura.getBytes(), "UTF-8");
		System.out.println("UTF-8: "+assinaturaUtF8);
		return assinaturaUtF8;
	}
	
	private org.w3c.dom.Document assinarDocumento(org.w3c.dom.Document doc, KeyStore ks, String alias, PrivateKey key, String pass) {          

		try {
		
			String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");  
			Provider provider = (Provider)Class.forName(providerName).newInstance();
			XMLSignatureFactory sig = XMLSignatureFactory.getInstance("DOM", provider); 

			TransformService ts = TransformService.getInstance(Transform.ENVELOPED, "DOM", provider);
			DOMTransform dt = new DOMTransform(ts);		
			Reference r= sig.newReference("", sig.newDigestMethod(DigestMethod.SHA1, null),Collections.singletonList(dt), null, null);
			
			List refs = new ArrayList();
			refs.add(r);
			
			ts = TransformService.getInstance(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, "DOM", provider);
			
			SignedInfo si = sig.newSignedInfo(sig.newCanonicalizationMethod  
					(CanonicalizationMethod.INCLUSIVE,  
						(C14NMethodParameterSpec) null),  
							sig.newSignatureMethod(SignatureMethod.RSA_SHA1, null),  
							Collections.singletonList(r)                          
			);  
			
			KeyInfoFactory kif = sig.getKeyInfoFactory();  
			
			List x509Content = new ArrayList();
			
			SsfProfileKeyStore profile = new SsfProfileKeyStore(ks, alias, pass);
			X509Certificate cert = (X509Certificate) profile.getCertificate();
			
			x509Content.add(cert);  
			
			X509Data xd = kif.newX509Data(x509Content);  
			KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));      
	          
			DOMSignContext dsc = new DOMSignContext(profile.getPrivateKey(), doc.getDocumentElement());  
		
			XMLSignature signature = sig.newXMLSignature(si, ki);
			
			signature.sign(dsc);  

		}catch (NoSuchAlgorithmException e){
			trace.addInfo("1-NoSuchAlgorithmException: " +e);
			e.printStackTrace();
		}
		catch (InvalidAlgorithmParameterException e) {
			trace.addInfo("2-InvalidAlgorithmParameterException: " +e);
			e.printStackTrace();
		} catch (MarshalException e) {
			trace.addInfo("3-MarshalException:  " +e);
			e.printStackTrace();
		} catch (XMLSignatureException e) {
			trace.addInfo("4-XMLSignatureException:  " +e);
			e.printStackTrace();
		} catch (KeyStoreException e) {
			trace.addInfo("5-KeyStoreException:  " +e);
			e.printStackTrace();
		} catch (InstantiationException e) {
			trace.addInfo("6-InstantiationException:  " +e);
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			trace.addInfo("7-IllegalAccessException:  " +e);
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			trace.addInfo("8-ClassNotFoundException:  " +e);
			e.printStackTrace();
		}
		
        
		return doc;
          
	}	

	public void setParameter(Map objparam) {
		  this.mapTrace = objparam;
		  if(objparam == null) {
			  this.mapTrace = new HashMap();
		  }

	}



}
